#ifndef __LINEMASK_H__
#define __LINEMASK_H__

#include "util/Pool.h"
#include <string.h>

// Holds a bitmask of up to MAX_BLOCK_SIZE/WORD_SIZE bits
class LineMask {
  private:
    static uint const NUM_BITS = MAX_BLOCK_SIZE / WORD_SIZE;
    static uint const NUM_WORDS = (NUM_BITS - 1) / WORD_SIZE + 1;

    uint data[NUM_WORDS];

  public:
    static const LineMask ALL_TRUE;
    static const LineMask ALL_FALSE;

    NEW_DELETE_OPERATORS_INLINE_H(LineMask,NoSuper);

    LineMask (bool const initialValue = false) {
        setAll(initialValue);
    }

    LineMask (LineMask const& rhs) {
        memcpy(data, rhs.data, sizeof(data));
    }

    ~LineMask () {}

    LineMask const& operator= (LineMask const& rhs) {
        memcpy(data, rhs.data, sizeof(data));
        return *this;
    }

    void clearAll () {
        memset(data, 0, sizeof(data));
    }

    void setAll (bool const value = true) {
        memset(data, value ? ~0 : 0, sizeof(data));
    }

    bool get (uint const index) const {        
        uint const w = (index / WORD_SIZE) % NUM_WORDS;
        uint const b = index & (WORD_SIZE - 1);
        return (data[w] & (1 << b)) != 0;
    }

    void clear (uint const index) {
        set(index, false);
    }

    void set (uint const index, bool const value = true) {
        uint const w = (index / WORD_SIZE) % NUM_WORDS;
        uint const b = index & (WORD_SIZE - 1);
        if (value) {
            data[w] |= (1 << b);
        } else {
            data[w] &= ~(1 << b);
        }
    }

    bool isAnySet () {
        for (uint i = 0; i < NUM_WORDS; ++i) {
            if (data[i] != 0) {
                return true;
            }
        }
        return false;
    }

    bool operator== (LineMask const& rhs) const {
        for (uint i = 0; i < NUM_WORDS; ++i) {
            if (data[i] != rhs.data[i]) {
                return false;
            }
        }
        return true;
    }

    LineMask operator& (LineMask const& rhs) const {
        LineMask result(rhs);
        for (uint i = 0; i < NUM_WORDS; ++i) {
            result.data[i] &= data[i];
        }
        return result;
    }

    LineMask operator| (LineMask const& rhs) const {
        LineMask result(rhs);
        for (uint i = 0; i < NUM_WORDS; ++i) {
            result.data[i] |= data[i];
        }
        return result;
    }
        
};

#endif // __LINEMASK_H__
